﻿#include "logic.h"
#include <time.h>

Plaid g_plaidArr[50][50];	//精灵数组
Game g_game;		//游戏状态
int run_time = 0;


//=========================================================
// 函数:void init(void)
// 作用:游戏初始化
//=========================================================
int init(void)
{
	//初始化SDL库
	if (initSDL() != 0)
	{
		return -1;
	}

	// 初始化单元格数组 ;
	initPlaid();
	
	return 0;
}




//=========================================================
//函数：void gameFree(void)
//作用；游戏资源释放
//=========================================================
void gameFree(void)
{
	//释放资源
	freeResources();

	//退出SDL库，释放窗口，渲染器
	freeSDL();
}


//=========================================================
// 函数: Uint32 timerFun(Uint32 interval, void * param)
// 作用：定时器响应函数
//=========================================================
Uint32 timerFun(Uint32 interval, void* param)
{
	//设置卡顿提示间隔10s
	if (run_time == 0) printf("定时函数启动\n");
	if(!(run_time % 10))printf("%d\n", run_time);
	run_time++;

	//修改时间
	if (g_game.gamestate == Ongoing) g_game.g_time++;

	//刷新窗口
	paint();

	return interval;
}

//=========================================================
// 函数: void start(void)
// 作用：游戏开始 (添加定时器，以及事件循环)
//=========================================================
void start(void)
{
	SDL_Event event; // 事件类型变量
	int nQuit = 0; //退出标识, 0循环，非0退出循环

	//游戏开始函数
	gameInit();

	//添加定时器函数，扫雷暂时不打算添加，遂放弃
	SDL_AddTimer(1000, timerFun, NULL);//第一个是延时ms，第二个调用的函数，第三个传入的指针，为NULL即可

	// 从消息队列中循环取得事件
	while (nQuit == 0) // 判断是否退出事件循环
	{
		while (SDL_PollEvent(&event)) // 获取事件
		{
			switch (event.type)//事件的类别
			{
			case SDL_QUIT: // 退出事件
				nQuit = 1;//用户激活退出事件，跳出循环
				break;
			case SDL_MOUSEBUTTONDOWN: // 鼠标按下事件
				mouseButtonEvent(&event);
				break;
			case SDL_MOUSEBUTTONUP: // 鼠标松开事件
				mouseButtonEvent(&event);
				break;
			default:
				break;
			}
		}
	}
}

//=========================================================
// 函数: void initPlaid(void)
// 作用：设置游戏起始状态,初始化单元格
//=========================================================
void initPlaid(void)
{
	g_game.gamestate = Ongoing;
	g_game.g_enjoy = EnjoyNormalUp;
	g_game.g_grades = 0;
	g_game.g_time = 0;

	g_game.g_unbombNum = BOMB_U_NUM;
	g_game.g_unPlaidXNum = BOMB_U_X;
	g_game.g_unPlaidYNum = BOMB_U_Y;

	//根据初始默认值设置大小和数量，默认值在data.h中
	switch (DEFAULT_MODE)
	{
	case 0:
		g_game.gamemode = ModeE;
		g_game.g_PlaidXNum = min(BOMB_E_X, g_game.g_MaxPlaidYNum);
		g_game.g_PlaidYNum = min(BOMB_E_Y, g_game.g_MaxPlaidYNum);
		g_game.g_bombNum = min(BOMB_E_NUM, g_game.g_PlaidXNum * g_game.g_PlaidYNum);
		break;
	case 1:
		g_game.gamemode = ModeN;
		g_game.g_PlaidXNum = min(BOMB_N_X, g_game.g_MaxPlaidYNum);
		g_game.g_PlaidYNum = min(BOMB_N_Y, g_game.g_MaxPlaidYNum);
		g_game.g_bombNum = min(BOMB_N_NUM, g_game.g_PlaidXNum * g_game.g_PlaidYNum);
		break;
	case 2:
		g_game.gamemode = ModeH;
		g_game.g_PlaidXNum = min(BOMB_H_X, g_game.g_MaxPlaidYNum);
		g_game.g_PlaidYNum = min(BOMB_H_Y, g_game.g_MaxPlaidYNum);
		g_game.g_bombNum = min(BOMB_H_NUM, g_game.g_PlaidXNum * g_game.g_PlaidYNum);
		break;
	case 3:
		g_game.gamemode = ModeU;
		g_game.g_PlaidXNum = min(BOMB_U_X, g_game.g_MaxPlaidYNum);
		g_game.g_PlaidYNum = min(BOMB_U_Y, g_game.g_MaxPlaidYNum);
		g_game.g_bombNum = min(BOMB_U_NUM, g_game.g_PlaidXNum * g_game.g_PlaidYNum);
		break;
	default:
		break;
	}
	
	

	//初始化单元格数组
	int i,j;
	for (i = 0; i < g_game.g_PlaidYNum; i++)
	{
		for (j = 0; j < g_game.g_PlaidXNum; j++)
		{
			g_plaidArr[i][j].type = TypeEmpty;
			g_plaidArr[i][j].type_un = TypeNormal;
			g_plaidArr[i][j].state = StateUnknow;		//控制游戏初始状态是否可见，便于调试
			g_plaidArr[i][j].initRect.w = PLAID_W;
			g_plaidArr[i][j].initRect.h = PLAID_H;

			g_plaidArr[i][j].initRect.x = (PLAID_W) * j + PLAID_1_X;
			g_plaidArr[i][j].initRect.y = (PLAID_H) * i + PLAID_1_Y;
		}
	}
}

//=========================================================
// 函数：void mouseButtonEvent(const SDL_Event * pEvent)
// 作用：处理鼠标按下事件
// 参数：事件类型指针
//=========================================================
void mouseButtonEvent(const SDL_Event* pEvent)
{
	int i, j;
	//左键按下
	if (pEvent->button.button == SDL_BUTTON_LEFT && pEvent->button.type == SDL_MOUSEBUTTONDOWN)
	{
		//开始游戏按钮
		if ((pEvent->button.x >= PATH_GAME_BEGIN_X)
			&& (pEvent->button.x <= PATH_GAME_BEGIN_X + PATH_GAME_W)
			&& (pEvent->button.y >= PATH_GAME_Y)
			&& (pEvent->button.y <= PATH_GAME_Y + PATH_GAME_H))
		{
			//开始游戏
			gameInit();
		}
		//结束按钮
		if ((pEvent->button.x >= PATH_GAME_END_X)
			&& (pEvent->button.x <= PATH_GAME_END_X + PATH_GAME_W)
			&& (pEvent->button.y >= PATH_GAME_Y)
			&& (pEvent->button.y <= PATH_GAME_Y + PATH_GAME_H)
			&& g_game.gamestate == Ongoing)
		{
			//设置游戏状态为结束
			g_game.gamestate = Fail;
		}

		//难度调整按钮
		if ((pEvent->button.x >= BUT_X)//上按钮
			&& (pEvent->button.x <= BUT_X + BUT_W)
			&& (pEvent->button.y >= BUT_UP_Y)
			&& (pEvent->button.y <= BUT_UP_Y + BUT_H))
		{
			//更改模式并开启游戏
			g_game.gamemode++;
			if (g_game.gamemode > 3) g_game.gamemode = 0;
			gameInit();
		}
		
		if ((pEvent->button.x >= BUT_X)//下按钮
			&& (pEvent->button.x <= BUT_X + BUT_W)
			&& (pEvent->button.y >= BUT_DOWN_Y)
			&& (pEvent->button.y <= BUT_DOWN_Y + BUT_H))
		{
			//更改模式并开启游戏
			g_game.gamemode--;
			if (g_game.gamemode < 0) g_game.gamemode = 3;
			gameInit();
		}

		//自定义难度部分
		if (g_game.gamemode == ModeU)
		{
			//确认
			if ((pEvent->button.x >= g_game.g_WindowX - SURE_X - SURE_W)
				&& (pEvent->button.x <= g_game.g_WindowX - SURE_X - SURE_W + SURE_W)
				&& (pEvent->button.y >= SURE_Y)
				&& (pEvent->button.y <= SURE_Y + SURE_H))
			{
				gameInit();
			}

			//难度调整按钮
			if ((pEvent->button.y >= BUT_UP_Y)//上按钮
				&& (pEvent->button.y <= BUT_UP_Y + BUT_H))
			{
				if ((pEvent->button.x >= g_game.g_WindowX - BUT_X_X)//横
					&& (pEvent->button.x <= g_game.g_WindowX - BUT_X_X + BUT_W))
				{
					g_game.g_unPlaidXNum = min(g_game.g_unPlaidXNum++, g_game.g_MaxPlaidXNum);
				}
				else if ((pEvent->button.x >= g_game.g_WindowX - BUT_Y_X)//竖
					&& (pEvent->button.x <= g_game.g_WindowX - BUT_Y_X + BUT_W))
				{
					g_game.g_unPlaidYNum = min(g_game.g_unPlaidYNum++, g_game.g_MaxPlaidYNum);
				}
				else if ((pEvent->button.x >= g_game.g_WindowX - BUT_N_X)//雷
					&& (pEvent->button.x <= g_game.g_WindowX - BUT_N_X + BUT_W))
				{
					g_game.g_unbombNum = min(g_game.g_unbombNum++, g_game.g_MaxPlaidXNum * g_game.g_MaxPlaidYNum);
				}
				paint();
			}
			if ((pEvent->button.y >= BUT_DOWN_Y)//下按钮
				&& (pEvent->button.y <= BUT_DOWN_Y + BUT_H))
			{
				if ((pEvent->button.x >= g_game.g_WindowX - BUT_X_X)//横
					&& (pEvent->button.x <= g_game.g_WindowX - BUT_X_X + BUT_W))
				{
					g_game.g_unPlaidXNum = max(g_game.g_unPlaidXNum-- , 0);
				}
				else if ((pEvent->button.x >= g_game.g_WindowX - BUT_Y_X)//竖
					&& (pEvent->button.x <= g_game.g_WindowX - BUT_Y_X + BUT_W))
				{
					g_game.g_unPlaidYNum = max(g_game.g_unPlaidYNum--, 0);
				}
				else if ((pEvent->button.x >= g_game.g_WindowX - BUT_N_X)//雷
					&& (pEvent->button.x <= g_game.g_WindowX - BUT_N_X + BUT_W))
				{
					g_game.g_unbombNum = max(g_game.g_unbombNum--, 0);
				}
				paint();
			}
		}

		//笑脸
		if ((pEvent->button.x >= (g_game.g_WindowX - ENJOY_W) / 2)//下按钮
			&& (pEvent->button.x <= (g_game.g_WindowX - ENJOY_W) / 2 + ENJOY_W)
			&& (pEvent->button.y >= 25)
			&& (pEvent->button.y <= 25 + ENJOY_H))
		{
			switch (g_game.gamestate)
			{
			case Ongoing:
				g_game.g_enjoy = EnjoyNormalDown;
				break;
			case Fail:
				g_game.g_enjoy = EnjoyFailDown;
				break;
			case Win:
				g_game.g_enjoy = EnjoyWinDown;
				break;
			default:
				break;
			}
			paint();
		}

		//单元格
		for (i = 0; i < 15; i++)
		{
			for (j = 0; j < 11; j++)
			{
				if ((pEvent->button.x >= g_plaidArr[i][j].initRect.x)
					&& (pEvent->button.x <= g_plaidArr[i][j].initRect.x + g_plaidArr[i][j].initRect.w)
					&& (pEvent->button.y >= g_plaidArr[i][j].initRect.y)
					&& (pEvent->button.y <= g_plaidArr[i][j].initRect.y + g_plaidArr[i][j].initRect.h)
					&& g_game.gamestate == Ongoing
					&& g_plaidArr[i][j].type_un == TypeNormal
					&& g_plaidArr[i][j].state == StateUnknow)
				{
					g_plaidArr[i][j].state = StateKnow;
					if (g_plaidArr[i][j].type == TypeBomb)
					{
						g_plaidArr[i][j].type = TypeBombed;
						g_game.gamestate = Fail;
						g_game.g_enjoy = EnjoyFailUp;
						playMusic();
					}
					if (g_plaidArr[i][j].type == TypeEmpty)
					{
						openEvery(i, j);
					}
					//判断游戏是否赢了
					gameflu();
					//绘制图形
					paint();
				}
			}
		}
	}

	//左键松开
	if (pEvent->button.button == SDL_BUTTON_LEFT && pEvent->button.type == SDL_MOUSEBUTTONUP)
	{

		//笑脸
		switch (g_game.gamestate)
		{
		case Ongoing:
			g_game.g_enjoy = EnjoyNormalUp;
			break;
		case Fail:
			g_game.g_enjoy = EnjoyFailUp;
			break;
		case Win:
			g_game.g_enjoy = EnjoyWinUp;
			break;
		default:
			break;
		}
		if ((pEvent->button.x >= (g_game.g_WindowX - ENJOY_W) / 2)//下按钮
			&& (pEvent->button.x <= (g_game.g_WindowX - ENJOY_W) / 2 + ENJOY_W)
			&& (pEvent->button.y >= 25)
			&& (pEvent->button.y <= 25 + ENJOY_H))
		{
			gameInit();
			paint();
		}
	}

	//右键
	else if (pEvent->button.button == SDL_BUTTON_RIGHT
				&& pEvent->button.type == SDL_MOUSEBUTTONDOWN
				&& g_game.gamestate == Ongoing)
	{
		for (i = 0; i < 15; i++)
		{
			for (j = 0; j < 11; j++)
			{
				if ((pEvent->button.x >= g_plaidArr[i][j].initRect.x)
					&& (pEvent->button.x <= g_plaidArr[i][j].initRect.x + g_plaidArr[i][j].initRect.w)
					&& (pEvent->button.y >= g_plaidArr[i][j].initRect.y)
					&& (pEvent->button.y <= g_plaidArr[i][j].initRect.y + g_plaidArr[i][j].initRect.h))
				{
					if (g_plaidArr[i][j].state == StateUnknow)
					{
						if (g_plaidArr[i][j].type_un == TypeEmpty)
						{
							g_plaidArr[i][j].type_un = TypeTag;
							//绘制图形
							paint();
							continue;
						}
						if (g_plaidArr[i][j].type_un == TypeTag) 
						{
							g_plaidArr[i][j].type_un = TypeQue;
							//绘制图形
							paint();
							continue;
						}
						if (g_plaidArr[i][j].type_un == TypeQue) 
						{
							g_plaidArr[i][j].type_un = TypeEmpty;
							//绘制图形
							paint();
							continue;
						}
					}
				}
			}
		}
	}
	//根据游戏状态进行相应动作
	gameOver();
}


//=========================================================
// 函数：void gameInit(void)
// 作用：设置游戏开始状态，生成地雷等操作
//=========================================================
void gameInit(void)
{

	int i=0, j=0 , bombnum;

	g_game.gamestate = Ongoing;
	g_game.g_enjoy = EnjoyNormalUp;
	g_game.g_grades = 0;
	g_game.g_time = 0;
	g_game.g_MusicWin = 0;

	srand((unsigned)time(NULL));

	//根据初难度设置大小和数量
	switch (g_game.gamemode)
	{
	case 0:
		g_game.gamemode = ModeE;
		g_game.g_PlaidXNum = min(BOMB_E_X, g_game.g_MaxPlaidXNum);
		g_game.g_PlaidYNum = min(BOMB_E_Y, g_game.g_MaxPlaidYNum);
		g_game.g_bombNum = min(BOMB_E_NUM, g_game.g_PlaidXNum * g_game.g_PlaidYNum);
		break;
	case 1:
		g_game.gamemode = ModeN;
		g_game.g_PlaidXNum = min(BOMB_N_X, g_game.g_MaxPlaidXNum);
		g_game.g_PlaidYNum = min(BOMB_N_Y, g_game.g_MaxPlaidYNum);
		g_game.g_bombNum = min(BOMB_N_NUM, g_game.g_PlaidXNum * g_game.g_PlaidYNum);
		break;
	case 2:
		g_game.gamemode = ModeH;
		g_game.g_PlaidXNum = min(BOMB_H_X, g_game.g_MaxPlaidXNum);
		g_game.g_PlaidYNum = min(BOMB_H_Y, g_game.g_MaxPlaidYNum);
		g_game.g_bombNum = min(BOMB_H_NUM, g_game.g_PlaidXNum * g_game.g_PlaidYNum);
		break;
	case 3:
		g_game.gamemode = ModeU;
		g_game.g_PlaidXNum = min(g_game.g_unPlaidXNum, g_game.g_MaxPlaidXNum);
		g_game.g_PlaidYNum = min(g_game.g_unPlaidYNum, g_game.g_MaxPlaidYNum);
		g_game.g_bombNum = min(g_game.g_unbombNum, g_game.g_PlaidXNum * g_game.g_PlaidYNum);
		break;
	default:
		printf("gameInit()出现错误\n");
		bombnum = BOMB_E_NUM;
		break;
	}

	//初始化单元格数组
	for (i = 0; i < g_game.g_PlaidYNum; i++)
	{
		for (j = 0; j < g_game.g_PlaidXNum; j++)
		{
			g_plaidArr[i][j].type = TypeEmpty;
			g_plaidArr[i][j].type_un = TypeNormal;
			g_plaidArr[i][j].state = StateUnknow;		//控制游戏初始状态是否可见，便于调试
			g_plaidArr[i][j].initRect.w = PLAID_W;
			g_plaidArr[i][j].initRect.h = PLAID_H;

			g_plaidArr[i][j].initRect.x = (PLAID_W)*j + PLAID_1_X;
			g_plaidArr[i][j].initRect.y = (PLAID_H)*i + PLAID_1_Y;
		}
	}

	//开始生成地雷
	bombnum = g_game.g_bombNum;

	while (bombnum != 0 && (g_game.g_PlaidXNum != 0 || g_game.g_PlaidYNum != 0))
	{
		i = max(0, rand() % g_game.g_PlaidYNum);
		j = max(0, rand() % g_game.g_PlaidXNum);

		if (g_plaidArr[i][j].type == TypeEmpty)
		{
			g_plaidArr[i][j].type = TypeBomb;
			bombnum--;
		}
	}

	//开始在地雷周围变成数字类型
	int  x, y, a;
	int dir[8][2] = { 0,1, 1,1, 1,0, 1,-1, 0,-1, -1,-1, -1,0, -1,1 };
	for (i = 0; i < g_game.g_PlaidYNum; i++)
	{
		for (j = 0; j < g_game.g_PlaidXNum; j++)
		{
			if (g_plaidArr[i][j].type != TypeBomb)
			{
				for (a = 0; a < 8; a++)
				{
					y = i + dir[a][0];
					x = j + dir[a][1];
					if (y >= 0 && y < g_game.g_PlaidYNum && x >= 0 && x < g_game.g_PlaidXNum
						&& g_plaidArr[y][x].type == TypeBomb)
					{
						g_plaidArr[i][j].type = TypeNum;
						continue;
					}
				}
			}
			
		}
	}

	//创建窗口
	loadWindows(g_game.g_PlaidXNum, g_game.g_PlaidYNum);
	//绘制界面
	paint();
}

//=========================================================
//函数：void gameOver(void)
// 作用：根据游戏状态进行相应动作
//=========================================================
void gameOver(void)
{
	int i, j;
	if (g_game.gamestate == Win)
	{
		switch (g_game.gamemode)
		{
		case ModeE:
			g_game.g_grades = BOMB_E_NUM;
			break;
		case ModeN:
			g_game.g_grades = BOMB_N_NUM;
			break;
		case ModeH:
			g_game.g_grades = BOMB_H_NUM;
			break;
		case ModeU:
			g_game.g_grades = g_game.g_unbombNum;
			break;
		default:
			printf("gameover()出现错误\n");
			break;
		}

		if (!g_game.g_MusicWin)
		{
			playMusic();
			g_game.g_MusicWin = 1;
		}
	}
	else if (g_game.gamestate == Fail)
	{
		g_game.g_grades = 0;
		for (i = 0; i < g_game.g_PlaidYNum; i++)
		{
			for (j = 0; j < g_game.g_PlaidXNum; j++)
			{
				if (g_plaidArr[i][j].type == TypeBomb
					&& g_plaidArr[i][j].type_un == TypeTag)
				{
					g_game.g_grades++;
				}
				if (g_plaidArr[i][j].type == TypeBomb
					&& g_plaidArr[i][j].type_un != TypeTag)
				{
					g_plaidArr[i][j].state = StateKnow;
				}
			}
		}
	}
	//更新分数
	paintScore();
}


//=========================================================
//函数：void openEvery(int x,int y)
// 作用：点一个空，打开周围的空
// 参数：输入当前点击的单元格
//=========================================================
void openEvery(int x,int y)
{
	int i, j, a;//高，宽
	int dir[8][2] = { 0,1, 1,1, 1,0, 1,-1, 0,-1, -1,-1, -1,0, -1,1 };

	if (g_plaidArr[x][y].state == StateKnow
		&& g_plaidArr[x][y].type == TypeEmpty)
	{
		for (a = 0; a < 8; a++)
		{
			j = y + dir[a][0];
			i = x + dir[a][1];
			if (j >= 0 && j < g_game.g_PlaidXNum && i >= 0 && i < g_game.g_PlaidYNum
				&& g_plaidArr[i][j].state == StateUnknow
				&& (g_plaidArr[i][j].type == TypeEmpty || g_plaidArr[i][j].type == TypeNum))
			{
				g_plaidArr[i][j].state = StateKnow;
				openEvery(i,j);
			}
		}
	}
}

//=========================================================
//函数：void gameflu(void)
// 作用：刷新游戏判断是否结束
//=========================================================
void gameflu(void)
{
	if (g_game.gamestate == Ongoing)
	{
		int UnknowNum = 0;
		for (int i = 0; i < g_game.g_PlaidYNum; i++)
		{
			for (int j = 0; j < g_game.g_PlaidXNum; j++)
			{
				if (g_plaidArr[i][j].state == StateUnknow)UnknowNum++;
			}
		}
		switch (g_game.gamemode)
		{
		case ModeE:
			if (UnknowNum == BOMB_E_NUM)g_game.gamestate = Win;
			break;
		case ModeN:
			if (UnknowNum == BOMB_N_NUM)g_game.gamestate = Win;
			break;
		case ModeH:
			if (UnknowNum == BOMB_H_NUM)g_game.gamestate = Win;
			break;
		case ModeU:
			if (UnknowNum == g_game.g_bombNum)g_game.gamestate = Win;
			break;
		default:
			break;
		}
		if (g_game.gamestate == Win) g_game.g_enjoy = EnjoyWinUp;
	}
}


